﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NCmd;
using UnityEngine;
using System.Net.Sockets;
using LitJson;

public interface IClient
{
    void ReciveCmd(NCmd.Cmd cmd);
}


public interface IServer
{
    void SendCmd(NCmd.Cmd cmd);
    void ReciveCmd(NCmd.Cmd cmd);
    void Connect(IClient net);
    void ReciveCmdStr(Type type, string cmdStr);
    bool IsConnected();
    void UnConnect(IClient net);
}

/// <summary>
/// 网络交互。
/// Unity中的操作只能在主线程。而消息监听在子线程,所以要通过缓存区处理。
/// </summary>
public class Net : Singleton<Net>, IClient
{
    IServer _server;

    Dictionary<Type, Action<NCmd.Cmd>> _cache { get { return _cmdEngine.CmdPaserCache;
} }
    List<NCmd.Cmd> _cmdThreadCache = new List<Cmd>();
    List<NCmd.Cmd> _cmdCache { get { return _cmdEngine.CmdCache; } }

    GameObject _netObj;
    CmdEngine _cmdEngine;

    // 网络消息，阻塞状态
    public bool PauseState
    {
        set
        {
            _cmdEngine.PauseState = value;
            if (value == true) { ReciveCmd(); }
        }
        get
        {
            return _cmdEngine.PauseState;
        }
    }

    public bool Connected
    {
        get
        {
            if (_server != null) { return _server.IsConnected(); }
            return false;
        }
    }

    public void Init()
    {
        _netObj = new GameObject("Net");
        GameObject.DontDestroyOnLoad(_netObj);
        _cmdEngine = _netObj.AddComponent<CmdEngine>();

        // 注册消息响应函数
        NetRegister.instance.Init(_cache);
    }
    public void Release()
    {
        if (_server != null) { _server.UnConnect(this); }
    }

    public bool ConnectServer(Action successCallback, Action failedCallback = null)
    {
        if (_server == null)
        {
            _server = new ServerInClientTcp();//new ServerInClient();//Server.Server.instance;
        }

        if (!Connected) { _server.Connect(this); }

        if (Connected)
        {
            if (successCallback != null) { successCallback.Invoke(); }
        }
        else
        {
            if (failedCallback != null) { failedCallback.Invoke(); }
            return false;
        }

        return true;
    }

    public void SendCmd(NCmd.Cmd cmd)
    {
        cmd.ClassName = cmd.GetType().FullName;
        _server.ReciveCmd(cmd);

        NetRegister.instance.CheckAndLogSend(cmd);
    }

    public void ReciveCmd(NCmd.Cmd curCmd = null)
    {
        if (curCmd != null)
        {
            _cmdCache.Add(curCmd);
        }
        return;

        // 线程用
        if (curCmd != null)
        {
            _cmdThreadCache.Add(curCmd);
        }
        if (PauseState)
        {
            return;
        }

        _cmdCache.AddRange(_cmdThreadCache);
        _cmdThreadCache.Clear();

        //foreach (var cmd in _cmdCache)
        //{
        //    Action<NCmd.Cmd> callback;
        //    if (_cache.TryGetValue(cmd.GetType(), out callback))
        //    {
        //        Debug.Log("<color=red>[client recive]</color>" + cmd.GetType());
        //        callback.Invoke(cmd);
        //    }
        //}
        //_cmdCache.Clear();
    }

    /// <summary>
    /// 检查消息类型
    /// </summary>
    /// <param name="cmd"></param>
    /// <param name="targetType"></param>
    /// <returns></returns>
    public static bool CheckCmdType(Cmd cmd, Type targetType)
    {
        if (cmd.GetType() != targetType)
        {
            Debug.LogError(string.Format("需要{0}类型，实际类型是：{1}", targetType, cmd.GetType()));
            return false;
        }

        return true;
    }
}
